11. Use a Service Locator

L5 P3 A07 Use A Service Locator

In this step you'll refactor your main application code to use your ServiceLocator.

Step 1: Use ServiceLocator in Application

  1. At the top level of your package hierarchy, open TodoApplication and create a val for your repository and assign it a repository that is obtained using ServiceLocator.provideTaskRepository:

TodoApplication.kt

class TodoApplication : Application() {

    val taskRepository: TasksRepository
        get() = ServiceLocator.provideTasksRepository(this)

    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) Timber.plant(DebugTree())
    }
}
  1. Open DefaultTasksRepository and delete the companion object:

DefaultTasksRepository.kt

//  DELETE THIS COMPANION OBJECT
companion object {
    @Volatile
    private var INSTANCE: DefaultTasksRepository? = null

    fun getRepository(app: Application): DefaultTasksRepository {
        return INSTANCE ?: synchronized(this) {
            val database = Room.databaseBuilder(app,
                ToDoDatabase::class.java, "Tasks.db")
                .build()
            DefaultTasksRepository(TasksRemoteDataSource, TasksLocalDataSource(database.taskDao())).also {
                INSTANCE = it
            }
        }
    }
}
  1. Open TaskDetailFragement and find the call to getRepository at the top of the class.
    Replace this call with a call that gets the repository from TodoApplication:

TaskDetailFragment.kt

// REPLACE this code
private val viewModel by viewModels<TaskDetailViewModel> {
    TaskDetailViewModelFactory(DefaultTasksRepository.getRepository(requireActivity().application))
}

// WITH this code

private val viewModel by viewModels<TaskDetailViewModel> {
    TaskDetailViewModelFactory((requireContext().applicationContext as TodoApplication).taskRepository)
}
  1. Do the same for TasksFragment:

TasksFragment.kt

// REPLACE this code
    private val viewModel by viewModels<TasksViewModel> {
        TasksViewModelFactory(DefaultTasksRepository.getRepository(requireActivity().application))
    }


// WITH this code

    private val viewModel by viewModels<TasksViewModel> {
        TasksViewModelFactory((requireContext().applicationContext as TodoApplication).taskRepository)
    }
  1. For StatisticsViewModel and AddEditTaskViewModel you should update the code that acquires the repository to use the repository from the TodoApplication as well:

TasksFragment.kt

// REPLACE this code
    private val tasksRepository = DefaultTasksRepository.getRepository(application)



// WITH this code

    private val tasksRepository = (application as TodoApplication).taskRepository
  1. Run your application (not the test)!

Since you only refactored, the app should run the same without issue.